package com.guguskins.back.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guguskins.back.common.constant.InventoryConstant;
import com.guguskins.back.common.constant.PropConstant;
import com.guguskins.back.common.exception.GlobalMsgException;
import com.guguskins.back.entity.*;
import com.guguskins.back.entity.bo.HenHouseRoteBo;
import com.guguskins.back.entity.vo.HenHousePrizeVo;
import com.guguskins.back.entity.vo.HenHouseTaskVo;
import com.guguskins.back.entity.vo.SimpleGoodsVo;
import com.guguskins.back.mapper.GuHenHouseTaskMapper;
import com.guguskins.back.service.*;
import com.guguskins.back.utils.CommonUtil;
import com.guguskins.back.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author mybatis-plus
 * @since 2021-06-28
 */
@Service
public class GuHenHouseTaskServiceImpl extends ServiceImpl<GuHenHouseTaskMapper, GuHenHouseTask> implements GuHenHouseTaskService {

    @Autowired
    private GuGoodsService goodsService;

    @Autowired
    private GuPropService propService;

    @Autowired
    private GuIncubationRateService incubationRateService;

    @Autowired
    private GuInventoryService inventoryService;

    @Autowired
    private GuPropNumService propNumService;

    @Autowired
    private GuUserService userService;

    @Override
    public HenHouseTaskVo getDetail(Long userId, Long pnId) {

        GuPropNum propNum = propNumService.getById(pnId);
        if (ObjectUtils.isEmpty(propNum)) {
            throw new GlobalMsgException("非法操作");
        }

        GuHenHouseTask task = this.getOne(new LambdaQueryWrapper<GuHenHouseTask>() {
            {
                select(GuHenHouseTask::getTaskId, GuHenHouseTask::getTaskGoodsId, GuHenHouseTask::getTaskEggType, GuHenHouseTask::getTaskLimitCard, GuHenHouseTask::getTaskExpirationTime, GuHenHouseTask::getTaskState);
                eq(GuHenHouseTask::getTaskUserId, userId);
                eq(GuHenHouseTask::getTaskHenHome, pnId);
                in(GuHenHouseTask::getTaskState, 1, 2);
            }
        });

        if (ObjectUtils.isEmpty(task)) {

            return HenHouseTaskVo
                    .builder()
                    .henHouseTask(new GuHenHouseTask())
                    .prop(new GuProp())
                    .goods(new SimpleGoodsVo())
                    .prizeGoods(new SimpleGoodsVo())
                    .state(0)
                    .build();
        }

        //修改任务状态
        if (task.getTaskExpirationTime().compareTo(LocalDateTime.now()) <= 0) {
            task.setTaskState(2);
            task.updateById();
        }

        GuGoods goods = goodsService.getById(task.getTaskGoodsId());
        SimpleGoodsVo goodsVo = new SimpleGoodsVo();
        goodsVo.setGoodsId(goods.getGoodsId());
        goodsVo.setGoodsIconUrl(goods.getGoodsIconUrl());
        GuProp prop = propService.getById(task.getTaskEggType());

        GuIncubationRate incubationRate = incubationRateService.getById(task.getTaskEggType());



        //计算最好孵化结果
        BigDecimal goodsPrice = goods.getGoodsPrice();
        BigDecimal minPrizePrice = goodsPrice.multiply(incubationRate.getMinPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
        BigDecimal maxPrizePrice = goodsPrice.multiply(incubationRate.getMaxPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);

        GuGoods prizeGoods = goodsService.getOne(new LambdaQueryWrapper<GuGoods>() {
            {
                le(GuGoods::getGoodsPrice, maxPrizePrice);
                last("limit 1");
            }
        });
        SimpleGoodsVo prizeGoodsVo = new SimpleGoodsVo();
        prizeGoodsVo.setGoodsId(prizeGoods.getGoodsId());
        prizeGoodsVo.setGoodsIconUrl(prizeGoods.getGoodsIconUrl());

        //计算坏蛋率
        BigDecimal smellEggRate = BigDecimal.ZERO;
        if (goodsPrice.compareTo(incubationRate.getSmellyEggValue()) < 0) {
            smellEggRate = BigDecimal.ONE.subtract(goodsPrice.divide(incubationRate.getSmellyEggValue(), BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
        }

        return HenHouseTaskVo.builder()
                .henHouseTask(task)
                .goods(goodsVo)
                .prop(prop)
                .prizeGoods(prizeGoodsVo)
                .smellyEggRate(smellEggRate)
                .minPrizePrice(minPrizePrice)
                .maxPrizePrice(maxPrizePrice)
                .state(task.getTaskState())
                .build();
    }

    @Override
    public HenHouseTaskVo getRote(Long userId, HenHouseRoteBo henHouseRoteBo) {
        HenHouseTaskVo henHouseTaskVo = new HenHouseTaskVo();

        GuIncubationRate incubationRate = null;

        if (!ObjectUtils.isEmpty(henHouseRoteBo.getPropId())) {

            GuProp prop = propService.getById(henHouseRoteBo.getPropId());
            incubationRate = incubationRateService.getById(henHouseRoteBo.getPropId());
            henHouseTaskVo.setProp(prop);
        }

        //查询库存
        if (!ObjectUtils.isEmpty(henHouseRoteBo.getInventoryId())) {

            GuInventory inventory = inventoryService.getById(henHouseRoteBo.getInventoryId());
            GuGoods goods = goodsService.getById(inventory.getInventoryItemId());
            SimpleGoodsVo goodsVo = new SimpleGoodsVo();
            henHouseTaskVo.setGoods(goodsVo);

            goodsVo.setGoodsId(goods.getGoodsId());
            goodsVo.setInventoryId(inventory.getInventoryId());
            goodsVo.setGoodsIconUrl(goods.getGoodsIconUrl());
            BigDecimal goodsPrice = goods.getGoodsPrice();
            if (!ObjectUtils.isEmpty(incubationRate)) {
                //饰品价值区间
                //计算孵化结果区间
                BigDecimal minPrizePrice = goodsPrice.multiply(incubationRate.getMinPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal maxPrizePrice = goodsPrice.multiply(incubationRate.getMaxPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                henHouseTaskVo.setMinPrizePrice(minPrizePrice);
                henHouseTaskVo.setMaxPrizePrice(maxPrizePrice);

                //计算最好孵化结果
                GuGoods prizeGoods = goodsService.getOne(new LambdaQueryWrapper<GuGoods>() {
                    {
                        le(GuGoods::getGoodsPrice, maxPrizePrice);
                        last("limit 1");
                    }
                });
                if (ObjectUtils.isEmpty(prizeGoods)) {
                    throw new GlobalMsgException("价值过低，请重新选择");
                }
                SimpleGoodsVo prizeGoodsVo = new SimpleGoodsVo();
                prizeGoodsVo.setGoodsId(prizeGoods.getGoodsId());
                prizeGoodsVo.setGoodsIconUrl(prizeGoods.getGoodsIconUrl());
                henHouseTaskVo.setPrizeGoods(prizeGoodsVo);

                //计算坏蛋率
                BigDecimal smellEggRate = BigDecimal.ZERO;
                if (goodsPrice.compareTo(incubationRate.getSmellyEggValue()) < 0) {
                    smellEggRate = BigDecimal.ONE.subtract(goodsPrice.divide(incubationRate.getSmellyEggValue(), BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
                }
                henHouseTaskVo.setSmellyEggRate(smellEggRate);

                GuHenHouseTask henHouseTask = new GuHenHouseTask();
                henHouseTask.setTaskExpirationTime(DateUtil.getTime(incubationRate.getTaskMarket()));
                henHouseTaskVo.setHenHouseTask(henHouseTask);
            }
        }
        return henHouseTaskVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submit(Long userId, HenHouseRoteBo henHouseRoteBo) {
        //校验鸡舍
        GuPropNum propNum = propNumService.getById(henHouseRoteBo.getPnId());
        int count = this.count(new LambdaQueryWrapper<GuHenHouseTask>() {
            {
                eq(GuHenHouseTask::getTaskHenHome, propNum.getId());
                in(GuHenHouseTask::getTaskState, 1, 2);
            }
        });
        if (count > 0) {
            throw new GlobalMsgException("鸡舍使用中");
        }
        //查询鸡蛋
        GuPropNum egg = propNumService.getOne(new LambdaQueryWrapper<GuPropNum>() {
            {
                eq(GuPropNum::getPropId, henHouseRoteBo.getPropId());
                eq(GuPropNum::getUserId, userId);
                last("limit 1");
            }
        });
        if (egg.getPropNum() <= 0) {
            throw new GlobalMsgException("暂无鸡蛋");
        }

        //校验库存状态
        GuInventory inventory = inventoryService.getById(henHouseRoteBo.getInventoryId());
        if (ObjectUtils.isEmpty(inventory) || !inventory.getInventoryUserId().equals(userId)) {
            throw new GlobalMsgException("非法操作");
        }
        if (!inventory.getInventoryState().equals(InventoryConstant.State.INVENTORY)) {
            throw new GlobalMsgException("库存状态异常");
        }

        //查询用户信息
        GuUser user = userService.getById(userId);
        //生成孵化任务
        GuHenHouseTask henHouseTask = new GuHenHouseTask();
        henHouseTask.setTaskUserId(userId);
        henHouseTask.setTaskSteamId(user.getUserSteamId());
        henHouseTask.setTaskHenHome(propNum.getId());
        henHouseTask.setTaskInventoryId(inventory.getInventoryId());
        henHouseTask.setTaskGoodsId(inventory.getInventoryItemId());
        henHouseTask.setTaskEggType(henHouseRoteBo.getPropId());
        //查询孵化时间
        GuIncubationRate incubationRate = incubationRateService.getById(henHouseRoteBo.getPropId());
        if (henHouseRoteBo.getSpeedCard() > 0) {
            //获取道具卡的库存
            GuPropNum speedCard = propNumService.getByUserIdAndPropId(userId, PropConstant.ACCELERATOR_CARD);
            if (speedCard.getPropNum() < 1) {
                throw new GlobalMsgException("暂无道具卡可使用");
            }
            henHouseTask.setTaskLimitCard(0);
            //天数转毫秒
            long expirationTimestamp = incubationRate.getTaskMarket() * 24 * 60 * 60 * 1000;
            expirationTimestamp = expirationTimestamp * 8 / 10;
            henHouseTask.setTaskExpirationTime(DateUtil.milliTimeToLocalDateTime(System.currentTimeMillis() + expirationTimestamp));
            //扣除道具卡
            //减少道具卡库存
            speedCard.setPropNum(speedCard.getPropNum() - 1);
            if (!speedCard.updateById()) {
                throw new GlobalMsgException("加速失败");
            }
        } else {
            henHouseTask.setTaskExpirationTime(DateUtil.getTime(incubationRate.getTaskMarket()));
        }
        //插入孵化任务
        if (henHouseTask.insert()) {
            //锁库存
            inventory.setInventoryState(InventoryConstant.State.INCUBATION_MATERIAL);
            if (!inventory.updateById()) {
                throw new GlobalMsgException("锁库存失败");
            }
            //锁鸡舍
            propNum.setPropState(2);
            if (!propNum.updateById()) {
                throw new GlobalMsgException("锁鸡舍失败");
            }

            //扣减鸡蛋
            egg.setPropNum(egg.getPropNum() - 1);
            if (!egg.updateById()) {
                throw new GlobalMsgException("扣减鸡蛋失败");
            }

            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean speedUp(Long userId, GuHenHouseTask henHouseTask) {
        GuHenHouseTask houseTask = this.getById(henHouseTask.getTaskId());
        if (ObjectUtils.isEmpty(houseTask) || !houseTask.getTaskUserId().equals(userId)) {
            throw new GlobalMsgException("非法参数");
        }
        if (houseTask.getTaskLimitCard() <= 0 || !houseTask.getTaskState().equals(1)) {
            throw new GlobalMsgException("此次孵化不能使用道具卡");
        }
//        List<Gu> props = propService.(userId);
        GuPropNum propNum = propNumService.getByUserIdAndPropId(userId, PropConstant.ACCELERATOR_CARD);
        if (propNum.getPropNum() < 1) {
            throw new GlobalMsgException("暂无道具卡可使用");
        }

        //扣减时间
        LocalDateTime taskExpirationTime = houseTask.getTaskExpirationTime();
        Long expirationTimestamp = DateUtil.localDateTime2Milli(taskExpirationTime);
        //当前时间戳
        long currentTimeMillis = System.currentTimeMillis();
        //获取加速时间戳
        long speedUpMillis = (expirationTimestamp - currentTimeMillis) * 8 / 10;
//        long speedUpMillis = (expirationTimestamp - currentTimeMillis) / 10;
        //计算加速后时间
        LocalDateTime speedUpExpiration = DateUtil.milliTimeToLocalDateTime(currentTimeMillis + speedUpMillis);

        houseTask.setTaskExpirationTime(speedUpExpiration);
//        houseTask.setTaskLimitCard(houseTask.getTaskLimitCard() - 1);
        if (!houseTask.updateById()) {
            throw new GlobalMsgException("加速失败");
        }
        //减少道具卡库存
        propNum.setPropNum(propNum.getPropNum() - 1);
        if (!propNum.updateById()) {
            throw new GlobalMsgException("加速失败");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancel(Long userId, GuHenHouseTask henHouseTask) {
        GuHenHouseTask houseTask = this.getById(henHouseTask.getTaskId());
        if (ObjectUtils.isEmpty(houseTask) || !houseTask.getTaskUserId().equals(userId)) {
            throw new GlobalMsgException("非法参数");
        }
        //更改状态
        houseTask.setTaskState(0);
        if (!houseTask.updateById()) {
            throw new GlobalMsgException("更改状态失败");
        }
        //修改库存
        GuInventory inventory = inventoryService.getById(houseTask.getTaskInventoryId());
        inventory.setInventoryState(InventoryConstant.State.INVENTORY);
        if (!inventory.updateById()) {
            throw new GlobalMsgException("修改库存状态失败");
        }
        //更改鸡舍状态
        GuPropNum propNum = propNumService.getById(houseTask.getTaskHenHome());
        propNum.setPropState(1);
        if (!propNum.updateById()) {
            throw new GlobalMsgException("修改鸡舍状态失败");
        }
        //返还鸡蛋
        GuPropNum eggNum = propNumService.getByUserIdAndPropId(userId, houseTask.getTaskEggType());
        eggNum.setPropNum(eggNum.getPropNum() + 1);
        if (!eggNum.updateById()) {
            throw new GlobalMsgException("返还鸡蛋失败");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HenHousePrizeVo receive(Long userId, GuHenHouseTask henHouseTask) {
        HenHousePrizeVo housePrizeVo = new HenHousePrizeVo();
        GuHenHouseTask houseTask = this.getById(henHouseTask.getTaskId());
        if (ObjectUtils.isEmpty(houseTask) || !houseTask.getTaskUserId().equals(userId)) {
            throw new GlobalMsgException("非法参数");
        }
        //校验任务状态
        if (!houseTask.getTaskState().equals(2)) {
            throw new GlobalMsgException("孵化状态异常");
        }
        //释放任务
        houseTask.setTaskState(3);
        if (!houseTask.updateById()) {
            throw new GlobalMsgException("更改孵化任务状态失败");
        }
        GuGoods goods = goodsService.getById(houseTask.getTaskGoodsId());
        BigDecimal goodsPrice = goods.getGoodsPrice();
        GuInventory inventory = inventoryService.getById(houseTask.getTaskInventoryId());
        GuPropNum henHouse = propNumService.getById(houseTask.getTaskHenHome());
        //释放库存
        inventory.setInventoryState(InventoryConstant.State.INVENTORY);
        if (!inventory.updateById()) {
            throw new GlobalMsgException("释放库存失败");
        }
        //释放鸡舍
        henHouse.setPropState(1);
        if (!henHouse.updateById()) {
            throw new GlobalMsgException("释放鸡舍失败");
        }

        //查看孵化概率
        GuIncubationRate incubationRate = incubationRateService.getById(1);
        //坏蛋率
        BigDecimal smellEggRate = BigDecimal.ZERO;
        if (goodsPrice.compareTo(incubationRate.getSmellyEggValue()) < 0) {
            smellEggRate = BigDecimal.ONE.subtract(goodsPrice.divide(incubationRate.getSmellyEggValue(), BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
        }
        if (smellEggRate.compareTo(BigDecimal.ZERO) >= 0) {
            if (CommonUtil.luckyDrawByRate(smellEggRate)) {
                // 返回前端坏蛋数据
                throw new GlobalMsgException("坏蛋");
//                System.err.println("坏蛋");
//                return new HenHousePrizeVo();
            }
        }

        BigDecimal minPrice;
        BigDecimal maxPrice;

        //判断是否是高区间
        if (CommonUtil.luckyDrawByRate(incubationRate.getHighRate())) {
            //高区间
            minPrice = goodsPrice.multiply(incubationRate.getMiddlePriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            maxPrice = goodsPrice.multiply(incubationRate.getMaxPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);

        } else {
            //低区间
            minPrice = goodsPrice.multiply(incubationRate.getMinPriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            maxPrice = goodsPrice.multiply(incubationRate.getMiddlePriceRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
        }

        //判断落咕币还是饰品
        if (CommonUtil.luckyDrawByRate(incubationRate.getGuCurrencyRate())) {
            //掉落咕币
            BigDecimal guCurrency = BigDecimal.valueOf(Math.random() * maxPrice.subtract(minPrice).doubleValue()).add(minPrice);
            if (!userService.addGuCurrency(userId, guCurrency, guCurrency, 5, null, null, null, null, null)) {
                throw new GlobalMsgException("增加咕币失败");
            }
            housePrizeVo.setGuCurrency(guCurrency);
        } else {
            //掉落饰品
            LambdaQueryWrapper<GuGoods> goodsLqw = new LambdaQueryWrapper<>();
            goodsLqw.ge(GuGoods::getGoodsPrice, minPrice);
            goodsLqw.ge(GuGoods::getGoodsPrice, maxPrice);
            List<GuGoods> goodsList = goodsService.list(goodsLqw);
            GuGoods prizeGoods = goodsList.get((int) (Math.random() * (goodsList.size())));
            houseTask.setTaskPrizeId(prizeGoods.getGoodsId());
            GuInventory guInventory = inventoryService.addInventory(userId, null, InventoryConstant.Type.GOODS, InventoryConstant.Source.HEN_HOUSE, houseTask.getTaskId(), prizeGoods.getGoodsId(), prizeGoods.getGoodsPrice());
            prizeGoods.setInventoryId(guInventory.getInventoryId());
            housePrizeVo.setPrizeGoods(prizeGoods);
        }
        return housePrizeVo;
    }
}
